# coding:utf-8

import time
import threading

def gen_coroutine(f):
    def wrapper(*args, **kwargs):
        gen_f = f()  # gen_f为生成器req_a
        r = gen_f.next()  # r为生成器long_io
        def fun(g):
            ret = g.next() # 执行生成器long_io
            try:
                gen_f.send(ret) # 将结果返回给req_a并使其继续执行
            except StopIteration:
                pass
        threading.Thread.start_new_thread(fun, (r,))
    return wrapper

def long_io():
    print("开始执行IO操作")
    time.sleep(5)
    print("完成IO操作，yield回操作结果")
    yield "io result"

@gen_coroutine
def req_a():
    print("开始处理请求req_a")
    ret = yield long_io()
    print("ret: %s" % ret)
    print("完成处理请求req_a")

def req_b():
    print("开始处理请求req_b")
    time.sleep(2)
    print("完成处理请求req_b")

def main():
    req_a()
    req_b()
    while 1:
        pass

if __name__ == '__main__':
    main()

'''
这个最终版本就是理解Tornado异步编程原理的最简易模型，但是，Tornado实现异步的机制不是线程，
而是epoll，即将异步过程交给epoll执行并进行监视回调。

需要注意的一点是，我们实现的版本严格意义上来说不能算是协程，因为两个程序的挂起与唤醒是在两个线程上实现的，
而Tornado利用epoll来实现异步，程序的挂起与唤醒始终在一个线程上，
由Tornado自己来调度，属于真正意义上的协程。虽如此，并不妨碍我们理解Tornado异步编程的原理。

'''